package paim.gh.model.pojos;


import java.util.ArrayList;
import java.util.List;

import javax.persistence.AccessType;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.OptimisticLockType;

import paim.wingchun.model.AField;
import paim.wingchun.model.AType;
import paim.wingchun.model.Replicable;
import paim.wingchun.model.Validacao;
import paim.wingchun.model.modelos.ErroModel;

@AType(rotulo = "Grade", rotuloS = "Grades")
@javax.persistence.Entity(access = AccessType.FIELD)
@org.hibernate.annotations.Entity(optimisticLock = OptimisticLockType.VERSION)
public class Grade extends AbstractTabela implements Replicable {

    private static final long serialVersionUID = 1L;

    // @Transient
    // // @OrderBy("ordemApresentacao")
    // @Cascade({
    // CascadeType.ALL,
    // CascadeType.DELETE,
    // CascadeType.DELETE_ORPHAN,
    // CascadeType.SAVE_UPDATE,
    // CascadeType.EVICT,
    // CascadeType.REFRESH })
    // @OneToMany(/* mappedBy = "grade", */fetch = FetchType.LAZY)
    // @JoinTable()
    @Cascade({ CascadeType.ALL, CascadeType.SAVE_UPDATE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN })
    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable()
    private List<Aula> aula = new ArrayList<>();

    @Cascade({ CascadeType.ALL, CascadeType.SAVE_UPDATE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN })
    @OneToMany(/* mappedBy = "grade", */fetch = FetchType.LAZY)
    @JoinTable()
    private List<Professor> professor = new ArrayList<>();

    /** balde comtem o que pode ser usado.<BR>
     * um balde deve servir a todas as grades de uma iteracao */
    @AField(isHidden = true)
    @Validacao(nulo = ErroModel.Level.NENHUM)
    @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.REFRESH })
    @ManyToOne(fetch = FetchType.EAGER, optional = true)
    @JoinColumn(nullable = false)
    private Balde balde = new Balde();

    @Transient
    /** indicador de que esta eh a grade principal escolhida pelo usuario */
    // @AField(rotulo = "Grade Principal", isHidden = true)
    // @Validacao(nulo = Level.NENHUM)
    // @Cascade({ CascadeType.EVICT, CascadeType.REFRESH })
    // @ManyToOne(fetch = FetchType.LAZY, optional = true)
    // @JoinColumn(nullable = true)
    private Grade gradeMestre;

    @Transient
    // @Cascade({ CascadeType.EVICT, CascadeType.REFRESH })
    // @OneToMany(/* mappedBy = "gradeMestre", */fetch = FetchType.LAZY)
    private List<Grade> gradesAlternativas = new ArrayList<>();

    // FIXME implementar
    @AField(isHidden = true)
    private transient Integer distancia;

    public List<Professor> getProfessor() {
        return this.professor;
    }

    public void setProfessor(List<Professor> professor) {
        this.professor = professor;
    }

    public void setBalde(Balde balde) {
        this.balde = balde;
    }

    public Balde getBalde() {
        return balde;
    }

    public void setGradesAlternativas(List<Grade> gradesAlternativas) {
        this.gradesAlternativas = gradesAlternativas;
    }

    public List<Grade> getGradesAlternativas() {
        return gradesAlternativas;
    }

    public void setDistancia(Integer distancia) {
        this.distancia = distancia;
    }

    public Integer getDistancia() {
        return distancia;
    }

    public void setGradeMestre(Grade gradeMestre) {
        this.gradeMestre = gradeMestre;
    }

    public Grade getGradeMestre() {
        return gradeMestre;
    }

    public List<Aula> getAula() {
        return this.aula;
    }

    public void setAula(List<Aula> aula) {
        this.aula = aula;
    }

    @Override
    public String toString() {
        return this.getSigla();
    }

    @Override
    public boolean equals(Object obj) {
        if ( !super.equals(obj) )
            return false;

        Grade other = (Grade) obj;

        if ( !equals(this.balde, other.balde) )
            return false;
        if ( !equals(this.gradeMestre, other.gradeMestre) )
            return false;

        return true;
    }

    @Override
    public Grade replica() {
        // TODO Auto-generated method stub
        /* deve replicar quase tudo */
        Grade replica = new Grade();
        return replica;

    }
}
